#include "Avalon/IO/BufferReader.hpp"
#include "Avalon/Threading/Async.hpp"

using namespace Avalon;
using namespace Avalon::IO;
using namespace Avalon::Threading;
using namespace std;

BufferReader::BufferReader(const Buffer& source)
    : m_source(source),
      m_readIterator(m_source.GetData()),
      m_readRemaining(m_source.GetSize()){}

BufferReader::BufferReader(const string& source) {
  m_source.Append(source.c_str(), static_cast<int>(source.size()));
  m_readIterator = m_source.GetData();
  m_readRemaining = m_source.GetSize();
}

BufferReader::~BufferReader() {}

bool BufferReader::IsAtEndOfDataSource() {
  return m_readRemaining == 0;
}

Async<int>::Ptr BufferReader::Read(Buffer* destination) {
  destination->Reserve(m_readRemaining);
  return Read(destination->GetMutableData(), m_readRemaining);
}

Async<int>::Ptr BufferReader::Read(void* destination, int size) {
  int sizeRead = min(size, m_readRemaining);
  memcpy(destination, m_readIterator, sizeRead);
  m_readRemaining -= sizeRead;
  m_readIterator += sizeRead;
  return NewAsync(sizeRead);
}

Async<int>::Ptr BufferReader::Read(Buffer* destination, int size) {
  int sizeRead = min(m_readRemaining, size);
  destination->Reserve(sizeRead);
  return Read(destination->GetMutableData(), sizeRead);
}
